@page "/theming"
@inherits AppComponentBase

@code {
    private IEnumerable<IBitComponentParams> _cascadingParams = new List<IBitComponentParams>
    {
        new BitCardParams { Background = BitColorKind.Primary, FullWidth = true, Style = "padding: 1.5rem" },
        new BitTextParams { Typography = BitTypography.Body1 },
        new BitTagParams { Color = BitColor.TertiaryBackground },
    };
}

<PageOutlet Url="theming"
            Title="Theming"
            Description="Customize the look and feel of bit BlazorUI components." />

<section class="page-container">
    <BitParams Parameters="_cascadingParams">
        <BitText Typography="BitTypography.H3">Theming</BitText>

        <br />

        <BitText Typography="BitTypography.H6">
            Using bit BlazorUI, you can customize the look and feel of your app using the theme features by specifying
            the color of the components, the darkness of the surfaces, the level of shadow, the appropriate opacity of elements, etc.
            <br /><br />
            Different aspects of the UI element styles are pre-defined in CSS variables that let you apply a consistent tone to your app.
            It allows you to customize all design aspects of your project to meet the specific needs of your business or brand.
            <br /><br />
            The default theme is based on the Microsoft Fluent design system with light and dark theme types available to choose from.
            By default, components use the light theme type.
        </BitText>
        
        <br /><br />

        <BitCard>
            <BitText Typography="BitTypography.H4">Quick setup</BitText>

            <br />

            <BitText>
                To get started with bit BlazorUI Theme as fast as possible, you can try the system theme feature of it.
                <br />
                First you need to register the bit BlazorUI services as follows:
            </BitText>

            <br />

            <CodeBox Language="csharp">builder.Services.AddBitBlazorUIServices();</CodeBox>

            <br />

            <BitText>
                And then add a specific attribute named <BitTag>bit-theme-system</BitTag> to the <BitTag>html</BitTag> tag:
            </BitText>

            <br />

            <CodeBox Language="html">&lt;html bit-theme-system>...&lt;/html></CodeBox>

            <br />

            <BitText>
                Now with this setup, the app will follow the system theme (dark or light) automatically.
            </BitText>
        </BitCard>

        <br />

        <BitCard>
            <BitText Typography="BitTypography.H4">CSS variables</BitText>

            <br />

            <BitText>
                All CSS variables defined in the Theme system of the bit BlazorUI are attached to the root element like this:
            </BitText>

            <br />

            <CodeBox Language="css">:root,
:root[bit-theme="light"],
:root[bit-theme="fluent"],
:root[bit-theme="fluent-light"] {

...

    --bit-clr-pri: #1A86D8;
    --bit-clr-pri-hover: #197FCD;
    --bit-clr-pri-active: #1779C2;
    --bit-clr-pri-dark: #096FBD;
    --bit-clr-pri-dark-hover: #0969B4;
    --bit-clr-pri-dark-active: #0864AA;
    --bit-clr-pri-light: #A3CFEF;
    --bit-clr-pri-light-hover: #8CC3EC;
    --bit-clr-pri-light-active: #76B6E8;
    --bit-clr-pri-text: #FFF;

...

}</CodeBox>

            <br />

            <BitText>
                The source code of these CSS variables is available in the
                <BitLink Href="https://github.com/bitfoundation/bitplatform/blob/main/src/BlazorUI/Bit.BlazorUI/Styles/Fluent" 
                         Target="_blank">
                    bit BlazorUI GitHub repo
                </BitLink>.
                You can simply override these values to customize the UI like what we did in our main website (<BitLink Href="https://bitplatform.dev">bitplatform.dev</BitLink>) in
                <BitLink Href="https://github.com/bitfoundation/bitplatform/blob/develop/src/Websites/Platform/src/Bit.Websites.Platform.Client/Styles/app.scss">
                    this file
                </BitLink>:
            </BitText>

            <br />

            <CodeBox Language="css">// overridden values:

:root[bit-theme="dark"] {
    --bit-clr-sec: transparent;
    --bit-clr-sec-hover: #061342;
    --bit-clr-bg-pri: #060E2D;
    --bit-clr-bg-sec: #0a153d;
    --bit-clr-bg-pri-hover: #07154a;
    --bit-clr-bg-pri-active: #061241;
    --bit-clr-bg-sec-hover: #07154a;
    --bit-clr-fg-sec: #dddddd;
}</CodeBox>

            <br />

            <BitText>
                <b>Note:</b> If you're using <BitTag>scss</BitTag> in your project, you can use <BitTag>_bit-css-variables.scss</BitTag>
                file which introduces scss variables for each bit theme css variable. you can find the latest version of this file
                <BitLink Href="https://github.com/bitfoundation/bitplatform/blob/main/src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Styles/abstracts/_bit-css-variables.scss" 
                Target="_blank">
                    here
                </BitLink>.
            </BitText>
        </BitCard>

        <br />

        <BitCard>
            <BitText Typography="BitTypography.H4">ThemeManager</BitText>

            <br />

            <BitText>
                In bit BlazorUI the <BitTag>BitThemeManager</BitTag> class is available to customize the Theme.
                <br />
                To start using the BitThemeManager, you first need to register bit BlazorUI services like this:
            </BitText>

            <br />

            <CodeBox Language="csharp">builder.Services.AddBitBlazorUIServices();</CodeBox>

            <br />

            <BitText>
                Now you can call methods of an injected instance of the <BitTag>BitThemeManager</BitTag>
                class to customize the UI:
            </BitText>

            <br />

            <CodeBox Language="csharp">[Inject] private BitThemeManager _bitThemeManager { get; set; }</CodeBox>

            <br />

            <BitText>
                For example using <BitTag>ApplyBitThemeAsync</BitTag> method and an instance of the
                <BitTag>BitTheme</BitTag> class, which contains the desired theme values,
                you can change the current theme styles.
                <br />
                The <BitTag>ApplyBitThemeAsync</BitTag> method accepts two parameters: a BitTheme instace
                and an optional target element which is by default the body element.
                <br />
                Here's an example of how to apply custom theme values to the entire body:
            </BitText>

            <br />

            <CodeBox Language="csharp">var myTheme = new BitTheme();
myTheme.Color.Foreground.Primary = "#111";
myTheme.Color.Background.Primary = "#777";
_bitThemeManager.ApplyBitThemeAsync(myTheme);</CodeBox>

            <br />

            <BitText>
                You can set the current theme using the <BitTag>SetThemeAsync</BitTag> method:
            </BitText>

            <br />

            <CodeBox Language="csharp">await _bitThemeManager.SetThemeAsync("fluent-dark");</CodeBox>

            <br />

            <BitText>
                You can also toggle current theme between dark/light using the
                <BitTag>ToggleDarkLightAsync</BitTag> method:
            </BitText>

            <br />

            <CodeBox Language="csharp">await _bitThemeManager.ToggleDarkLightAsync();</CodeBox>

            <br />

            <BitText>
                This method returns the name of the new toggled theme.
                <br />
                The <BitTag>BitThemeManager</BitTag> has a method named <BitTag>GetCurrentThemeAsync</BitTag>
                which returns the name of the current theme:
            </BitText>

            <br />

            <CodeBox Language="csharp">var currentTheme = await _bitThemeManager.GetCurrentThemeAsync();</CodeBox>
        </BitCard>

        <br />

        <BitCard>
            <BitText Typography="BitTypography.H4">System Theme</BitText>

            <br />

            <BitText>
                Using bit BlazorUI, you can use the system theme as the default theme when the app starts up.
                <br />
                In order to enable this feature a specific attribute named
                <BitTag>bit-theme-system</BitTag> should be added to the <BitTag>html</BitTag> tag:
            </BitText>

            <br />

            <CodeBox Language="html">&lt;html bit-theme-system>...&lt;/html></CodeBox>
        </BitCard>

        <br />

        <BitCard>
            <BitText Typography="BitTypography.H4">Persist Theme</BitText>

            <br />

            <BitText>
                Using bit BlazorUI, you can persist the current theme in the local storage.
                <br />
                To enable this feature a specific attribute named
                <BitTag>bit-theme-persist</BitTag> should be added to the <BitTag>html</BitTag> tag:
            </BitText>

            <br />

            <CodeBox Language="html">&lt;html bit-theme-persist>...&lt;/html></CodeBox>
        </BitCard>

        <br />

        <BitCard>
            <BitText Typography="BitTypography.H4">Default Theme</BitText>

            <br />

            <BitText>
                Using bit BlazorUI, you can change the default theme which is <BitTag>light</BitTag> using a specific attribute named
                <BitTag>bit-theme-default</BitTag> on the <BitTag>html</BitTag> tag:
            </BitText>

            <br />

            <CodeBox Language="html">&lt;html bit-theme-default="dark">...&lt;/html></CodeBox>
        </BitCard>

        <br />

        <BitCard>
            <BitText Typography="BitTypography.H4">Customizing theme names</BitText>
            
            <br />

            <BitText>
                In bit BlazorUI, the default name of the available themes are <BitTag>light</BitTag> and <BitTag>dark</BitTag>.
                you can change these default names using the following attributes on the <BitTag>html</BitTag> tag:
            </BitText>

            <br />

            <CodeBox Language="html">&lt;html bit-theme-dark="custom-dark" bit-theme-light="custom-light">...&lt;/html></CodeBox>
        </BitCard>

        <br />

        <BitCard>
            <BitText Typography="BitTypography.H4">CSS in C#</BitText>
            
            <br />

            <BitText>
                In bit BlazorUI, the <BitTag>BitCss</BitTag> class is available to access theme related CSS classes & variables in C#.
                <br />
                You can use different properties of this class to further customize your UI:
            </BitText>

            <br />

            <CodeBox Language="html">&lt;html>
    &lt;head>...&lt;/head>
    &lt;body class="@@BitCss.Class.Color.Background.Primary @@BitCss.Class.Color.Foreground.Primary">
        ...
    &lt;/body>
&lt;/html></CodeBox>

            <br />

            <BitText>
                This class contians two main property for accessing CSS classes (<BitTag>BitCss.Class</BitTag>) and CSS variables (<BitTag>BitCss.Var</BitTag>).
            </BitText>

            <br />

            <CodeBox Language="html">&lt;div style="border-color:var(@@BitCss.Var.Color.Border.Secondary)">
    hello world!
&lt;/div></CodeBox>

        </BitCard>

        <br />

        <BitCard>
            <BitText Typography="BitTypography.H4">ThemeProvider</BitText>

            <br />

            <BitText>
                In bit BlazorUI, the <BitTag>BitThemeProvider</BitTag> component is available to further customize the Theme.
                <br />
                You can wrap any elements with the <BitTag>BitThemeProvider</BitTag> component and assign an instance of <BitTag>BitTheme</BitTag> to it:
            </BitText>

            <br />

            <CodeBox Language="cshtml">&lt;BitThemeProvider Theme="myTheme">
    &lt;BitCheckbox Label="Check me!" />
&lt;/BitThemeProvider>

@@code {
    BitTheme myTheme = new()
    {
        Color = { Primary = { Main = "red" } }
    };
}</CodeBox>

            <br />

            <BitText>
                The applied theme provided by the <BitTag>BitThemeProvider</BitTag> can be accessed directly using a CascadingParameter in the child components:
            </BitText>

            <br />

            <CodeBox Language="csharp">[CascadingParameter] public BitTheme? Theme { get; set; }</CodeBox>

            <br />

            <BitText>
                You can also nest <BitTag>BitThemeProvider</BitTag> components to achieve the desired style:
            </BitText>

            <br />

            <CodeBox Language="cshtml">&lt;BitThemeProvider Theme="myTheme">
    &lt;BitCheckbox Label="Check me!" />
    &lt;BitThemeProvider Theme="myTheme2">
        &lt;BitCheckbox Label="Check me 2!" />
    &lt;/BitThemeProvider>
&lt;/BitThemeProvider>

@@code {
    BitTheme myTheme = new()
    {
        Color = { Primary = { Main = "red" } }
    };

    BitTheme myTheme2 = new()
    {
        Color = { Primary = { Main = "blue" } }
    };
}</CodeBox>
        </BitCard>

        <br />

        <BitCard>
            <BitText Typography="BitTypography.H4">JavaScript API</BitText>
            
            <br />

            <BitText>
                bit BlazorUI has a rather extensive JavaScript API through <BitTag>BitTheme</BitTag> javascript object
                to customize the UI of the app even further.
                <br />
                The differnet functions available in this object are as follows:
            </BitText>

            <br /><br />

            <BitText>
                <b>get</b>: gets the current theme.
            </BitText>

            <CodeBox Language="js">const currentTheme = BitTheme.get();</CodeBox>

            <br /><br />
            
            <BitText>
                <b>set</b>: sets the current theme.
            </BitText>

            <CodeBox Language="js">BitTheme.set('dark');</CodeBox>

            <br /><br />

            <BitText>
                <b>toggleDarkLight</b>: toggles the current theme between dark & light.
            </BitText>

            <CodeBox Language="js">BitTheme.toggleDarkLight();</CodeBox>

            <br /><br />

            <BitText>
                <b>useSystem</b>: uses the current theme of the system (dark or light) as the app theme.
            </BitText>

            <CodeBox Language="js">BitTheme.useSystem();</CodeBox>

            <br /><br />

            <BitText>
                <b>onChange</b>: an event that fires when the current theme changes.
            </BitText>

            <CodeBox Language="js">BitTheme.onChange((newTheme, oldTheme) => {
    if (newTheme.includes('dark')) {
        document.querySelector("meta[name=theme-color]")!.setAttribute('content', '#0d1117');
    } else {
        document.querySelector("meta[name=theme-color]")!.setAttribute('content', '#ffffff');
    }
});</CodeBox>

            <br /><br />

            <BitText>
                <b>applyBitTheme</b>: applies an instance of BitTheme to the specified element or the body element, just like the
                <BitTag>ApplyBitThemeAsync</BitTag> method of the <BitTag>BitThemeManager</BitTag>.
            </BitText>

            <CodeBox Language="js">BitTheme.applyBitTheme({ '--bit-clr-pri': '#1A86D8' }, myElement)</CodeBox>

            <br /><br />

            <BitText>
                <b>isSystemDark</b>: checks if the current theme of the system is dark.
            </BitText>

            <CodeBox Language="js">BitTheme.isSystemDark();</CodeBox>

            <br /><br />

            <BitText>
                <b>init</b>: initializes the BitTheme object using the provided options.
            </BitText>

            <CodeBox Language="js">BitTheme.init({
    system: true,
    persist: true,
    theme: 'custom-dark',
    default: 'custom-dark',
    darkTheme: 'custom-dark',
    lightTheme: 'custom-light',
    onChange: (newTheme: string, oldTheme: string) => {
        if (newTheme === 'custom-dark') {
            document.querySelector("meta[name=theme-color]")!.setAttribute('content', '#0d1117');
        } else {
            document.querySelector("meta[name=theme-color]")!.setAttribute('content', '#ffffff');
        }
    }
});</CodeBox>
        </BitCard>

        <br />

        <FeedbackSection Url="ThemingPage.razor" />
    </BitParams>
</section>
